package com.dimenlink.web.controller;

import com.dimenlink.entity.constants.Constants;
import com.dimenlink.entity.dto.TokenUserInfoDto;
import com.dimenlink.entity.enums.CommentTopTypeEnum;
import com.dimenlink.entity.enums.PageSize;
import com.dimenlink.entity.enums.UserActionTypeEnum;
import com.dimenlink.entity.po.UserAction;
import com.dimenlink.entity.po.VideoComment;
import com.dimenlink.entity.po.VideoInfo;
import com.dimenlink.entity.query.UserActionQuery;
import com.dimenlink.entity.query.VideoCommentQuery;
import com.dimenlink.entity.vo.PaginationResultVO;
import com.dimenlink.entity.vo.ResponseVO;
import com.dimenlink.entity.vo.VideoCommentResultVO;
import com.dimenlink.service.UserActionService;
import com.dimenlink.service.VideoCommentService;
import com.dimenlink.service.VideoInfoService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.Resource;
import javax.validation.constraints.NotEmpty;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Size;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

@RestController
@RequestMapping("/comment")
@Validated
@Slf4j
public class VideoCommentController extends ABaseController{

    @Resource
    private VideoCommentService videoCommentService;
    @Resource
    private UserActionService userActionService;
    @Resource
    private VideoInfoService videoInfoService;

    @RequestMapping("/postComment")
    public ResponseVO postComment(@NotEmpty String videoId,
                                  @NotEmpty @Size(max = 500) String content,
                                  Integer replyCommentId,
                                  @Size(max = 50) String imgPath) {

        TokenUserInfoDto tokenUserInfoDto = getTokenUserInfoDto();
        VideoComment comment = new VideoComment();
        comment.setUserId(tokenUserInfoDto.getUserId());
        comment.setAvatar(tokenUserInfoDto.getAvatar());
        comment.setNickName(tokenUserInfoDto.getNickName());
        comment.setVideoId(videoId);
        comment.setContent(content);
        comment.setImgPath(imgPath);
        videoCommentService.postComment(comment, replyCommentId);
        return getSuccessResponseVO(comment);
    }


    @RequestMapping("/loadComment")
    public ResponseVO loadComment(
            @NotEmpty String videoId,  // 视频ID，不能为空，用于标识要加载评论的视频
            Integer pageNo,  // 页码，用于分页查询，可为空
            Integer orderType  // 排序类型，用于决定评论的排序方式，可为空
    ) {
        // 根据视频ID获取视频信息，用于后续判断评论区是否关闭等逻辑
        VideoInfo videoInfo = videoInfoService.getVideoInfoByVideoId(videoId);
        // 判断视频互动信息中是否包含代表“关闭评论区”的标识
        if (videoInfo.getInteraction() != null && videoInfo.getInteraction().contains(Constants.ZERO.toString())) {
            // 若评论区已关闭，返回一个包含空列表的成功响应
            return getSuccessResponseVO(new ArrayList<>());
        }

        // 构建评论查询对象，用于封装查询条件
        VideoCommentQuery commentQuery = new VideoCommentQuery();
        commentQuery.setVideoId(videoId);  // 设置要查询评论的视频ID
        commentQuery.setLoadChildren(true);// 设置是否加载子评论
        commentQuery.setPageNo(pageNo);  // 设置查询的页码
        // 设置每页显示的评论数量，这里使用 PageSize.SIZE15 定义的数量
        commentQuery.setPageSize(PageSize.SIZE15.getSize());
        commentQuery.setpCommentId(0);  // 设置上级评论ID为 0 ，表示查询一级评论

        // 根据排序类型，拼接排序规则字符串：
        // 若 orderType 为 null 或 0 ，按“点赞数降序、评论ID降序”排序；否则按“评论ID降序”排序
        String orderBy = orderType == null || orderType == 0
                ? "like_count desc,comment_id desc"
                : "comment_id desc";
        commentQuery.setOrderBy(orderBy);  // 设置排序规则到查询对象

        // 调用视频评论服务，按分页和查询条件获取评论数据
        PaginationResultVO<VideoComment> commentData = videoCommentService.findListByPage(commentQuery);

        // 当 pageNo 为 null 时，执行置顶评论相关处理逻辑
        if (pageNo == null) {
            // 调用 topComment 方法，根据视频ID获取已置顶的评论列表
            List<VideoComment> topCommentList = topComment(videoId);
            // 检查获取到的置顶评论列表是否不为空
            if (!topCommentList.isEmpty()) {
                // 从 commentData（分页结果对象，包含普通评论列表等数据）的列表中，过滤掉与置顶评论列表中第一个评论ID相同的评论
                // 这里通过 Java 8 的 Stream API 实现过滤：筛选出评论ID不等于置顶评论列表第一个元素评论ID的普通评论，重新收集成新列表
                List<VideoComment> commentList = commentData.getList().stream()
                        .filter(item -> !item.getCommentId().equals(topCommentList.get(0).getCommentId()))
                        .collect(Collectors.toList());
                // 将置顶评论列表插入到新普通评论列表的最前面（索引为0的位置），这样置顶评论就会在最终展示列表的首位
                commentList.addAll(0, topCommentList);
                // 把重新组装好的评论列表（普通评论 + 置顶评论）设置回 commentData 中，用于后续返回给前端或其他处理
                commentData.setList(commentList);
            }
        }

        // 构建评论结果 VO 对象，用于封装最终返回给前端的数据
        VideoCommentResultVO resultVO = new VideoCommentResultVO();
        resultVO.setCommentData(commentData);  // 设置分页的评论数据到结果对象

        // 初始化用户操作列表，用于记录当前用户对该视频评论的互动操作（点赞、点踩、投币等 ）
        List<UserAction> userActionList = new ArrayList<>();
        // 获取当前用户的令牌信息（包含用户ID等 ），用于查询该用户的操作记录
        TokenUserInfoDto tokenUserInfoDto = getTokenUserInfoDto();
        // 若用户令牌信息不为空（即用户已登录 ）
        if (tokenUserInfoDto != null) {
            // 构建用户操作查询对象，封装查询条件
            UserActionQuery actionQuery = new UserActionQuery();
            actionQuery.setVideoId(videoId);  // 设置操作对应的视频ID
            // 设置操作的用户ID为当前登录用户的ID
            actionQuery.setUserId(tokenUserInfoDto.getUserId());
            // 设置要查询的操作类型数组，包含“评论点赞、评论点踩”（根据枚举定义 ）
            actionQuery.setActionTypeArray(new Integer[]{
                    UserActionTypeEnum.COMMENT_LIKE.getType(),
                    UserActionTypeEnum.COMMENT_HATE.getType()
            });
            // 调用用户操作服务，根据条件查询用户对该视频的操作记录
            userActionList = userActionService.findListByParam(actionQuery);
        }
        // 将查询到的用户操作列表设置到结果对象中
        resultVO.setUserActionList(userActionList);

        // 返回包含评论结果数据的成功响应，最终会将 resultVO 数据返回给前端
        return getSuccessResponseVO(resultVO);
    }

    private List<VideoComment> topComment(String videoId) {
        // 创建 VideoCommentQuery 对象，用于封装查询条件
        VideoCommentQuery commentQuery = new VideoCommentQuery();

        commentQuery.setVideoId(videoId);

        // 设置置顶类型
        commentQuery.setTopType(CommentTopTypeEnum.TOP.getType());

        // 设置是否加载子评论：开启加载子评论功能，查询时会同时获取当前评论的子评论（嵌套查询）
        commentQuery.setLoadChildren(true);

        //执行查询：调用 videoCommentService 的 findListByParam 方法，根据上面设置的条件查询评论列表
        List<VideoComment> videoCommentList = videoCommentService.findListByParam(commentQuery);

        return videoCommentList;
    }

    @RequestMapping("/topComment")
    public ResponseVO topComment(@NotNull Integer commentId) {
        TokenUserInfoDto tokenUserInfoDto = getTokenUserInfoDto();
        videoCommentService.topComment(commentId, tokenUserInfoDto.getUserId());
        return getSuccessResponseVO(null);
    }

    @RequestMapping("/cancelTopComment")
    public ResponseVO cancelTopComment(@NotNull Integer commentId) {
        TokenUserInfoDto tokenUserInfoDto = getTokenUserInfoDto();
        videoCommentService.cancelTopComment(commentId, tokenUserInfoDto.getUserId());
        return getSuccessResponseVO(null);
    }

    @RequestMapping("/userDelComment")
    public ResponseVO userDelComment(@NotNull Integer commentId) {
        TokenUserInfoDto tokenUserInfoDto = getTokenUserInfoDto();
        videoCommentService.deleteComment(commentId, tokenUserInfoDto.getUserId());
        return getSuccessResponseVO(null);
    }
}
